package com.onadake.dao;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.annotations.Param;

import com.onadake.domain.Data;
import com.onadake.domain.EntityType;
import com.onadake.domain.RelationType;
import com.onadake.domain.query.Criterium;
import com.onadake.domain.query.Filter;

/**
 * My batis mapper for entity objects.
 * 
 * @author radek.hecl
 *
 */
public interface MyBatisEntityMapper {

    /**
     * Inserts the entity core.
     * 
     * @param code code of the entity, this is the unique identifier
     * @param name name of the entity
     * @param utcCreatedTimestamp timestamp when entity was created in UTC time zone
     * @param type type of the entity
     */
    public void insertCore(
            @Param("code") String code,
            @Param("name") String name,
            @Param("utcCreatedTimestamp") Date utcCreatedTimestamp,
            @Param("type") EntityType type);
    
    /**
     * Inserts profile for the specified entity.
     * 
     * @param code code of the entity
     * @param profile profile to be inserted
     */
    public void insertProfile(@Param("code") String code, @Param("profile") Map<String, String> profile);

    /**
     * Insert join into specified table for the specified entity.
     * 
     * @param code code of the entity
     * @param table table for join
     * @param join join values for the table
     */
    public void insertJoin(@Param("table") String table, @Param("code") String code, @Param("join") Map<String, Object> join);

    /**
     * Selects entities core according the filter.
     * 
     * @param filter filter to be used
     * @return list with selected entities
     */
    public List<Map<String, Object>> selectCores(@Param("joins") Map<String, Set<String>> joins, @Param("filter") Filter<String> filter);

    /**
     * Selects profiles for the specified entities.
     * 
     * @param ids ids of entities for which profiles are requested
     * @return list with selected profiles
     */
    public List<Map<String, Object>> selectProfiles(@Param("ids") Set<Long> ids);

    /**
     * Counts cores.
     * 
     * @param tables tables which are involved in counting
     * @param criteria criteria used for counting
     * @return how many entities satisfies the criteria
     */
    public long countCores(@Param("tables") Set<String> tables, @Param("criteria") Set<Criterium<String>> criteria);

    /**
     * Deletes the specified entity.
     * 
     * @param code entity code
     */
    public void deleteEntity(@Param("code") String code);
    
    /**
     * Deletes profile of the specified entity.
     * 
     * @param code entity code
     */
    public void deleteProfile(@Param("code") String code);
    
    /**
     * Updates entity name.
     * 
     * @param code code of the entity
     * @param name name of the entity
     */
    public void updateName(@Param("code") String code, @Param("name") String name);
    
    /**
     * Updates join.
     * 
     * @param code code of the entity
     * @param table table which will be updated
     * @param column column which will be updated
     * @param value value which will be used
     */
    public void updateJoin(@Param("code") String code, @Param("table") String table,
            @Param("column") String column, @Param("value") Object value);
    
    /**
     * Inserts new relation.
     * 
     * @param subjectCode subject entity code
     * @param objectCode object entity code
     * @param type type of the relation
     */
    public void insertRelation(@Param("subjectCode") String subjectCode,
            @Param("objectCode") String objectCode,
            @Param("type") RelationType type);

    /**
     * Deletes relation.
     * 
     * @param subjectCode subject entity code
     * @param objectCode object entity code
     * @param type type of the relation
     */
    public void deleteRelation(@Param("subjectCode") String subjectCode,
            @Param("objectCode") String objectCode,
            @Param("type") RelationType type);

    /**
     * Selects relations according the filter.
     * 
     * @param filter filter to be used
     * @return list with selected relations
     */
    public List<Map<String, Object>> selectRelations(@Param("filter") Filter<String> filter);

    /**
     * Counts relations.
     * 
     * @param criteria criteria used for counting
     * @return how many relations satisfies the criteria
     */
    public long countRelations(@Param("criteria") Set<Criterium<String>> criteria);
    
    /**
     * Inserts data block
     * 
     * @param data data object which will be inserted
     * @param blob data blob
     */
    public void insertData(@Param("data") Data data, @Param("blob") byte[] blob);

    /**
     * Deletes data block for the specified entity.
     * 
     * @param data data object to be deleted
     */
    public void deleteData(@Param("data") Data data);

    
    /**
     * Selects all data blocks according filter.
     * 
     * @param filter filter object
     * @return data blocks which matches the filter
     */
    public List<Map<String, Object>> selectDatas(@Param("filter") Filter<String> filter);

    /**
     * Counts how many data blocks satisfies the criteria.
     * 
     * @param criteria criteria to be satisfied
     * @return how many data blocks satisfies the criteria
     */
    public long countDatas(@Param("criteria") Set<Criterium<String>> criteria);

    
    /**
     * Selects data blob for the particular data object.
     * 
     * @param data data object to be used
     * @return data blob
     */
    public List<Map<String, Object>> selectDataBlob(@Param("data") Data data);

}
